﻿using System.Collections.Generic;
using Abp.Application.Services;
using Abp.Application.Services.Dto;
using Abp.Domain.Repositories;
using Batman.Cms.Core.Models.Mvc;
using Batman.Core;
using Batman.Jianbei.Forum.Areas.Forum.Filters;
using Batman.Jianbei.Forum.Areas.Forum.Responses;
using Batman.Jianbei.Forum.Core.Domains.Posts;
using Batman.Jianbei.Forum.Core.Domains.Users;
using Omu.ValueInjecter;
using System.Linq;
using System.Linq.Dynamic.Core;
using Microsoft.EntityFrameworkCore;
using Batman.Jianbei.Forum.Core;
using Batman.Cms.Core.Commands;
using Abp.Dapper.Repositories;

namespace Batman.Jianbei.Forum.Services.Posts
{
    public class CommentService : ForumService
    {
        public IRepository<PostComment, string> Repo { get; set; }

        public IRepository<WeixinUser, string> WeixinUserRepo { get; set; }

        public IDapperRepository<Post, string> PostRepo { get; set; }

        /// <summary>
        /// 添加评论
        /// </summary>
        /// <param name="model"></param>
        /// <param name="wxUID"></param>
        /// <returns></returns>
        public ResponseBase<PostComment> AddPostComment(CommentPostInput model, string wxUID)
        {
            PostComment postComment = new PostComment(wxUID).InjectFrom(model) as PostComment;

            var newComment = Repo.Insert(postComment);

            return new ResponseBase<PostComment>() { Result = newComment };
        }

        /// <summary>
        /// 获取评论列表分页
        /// </summary>
        /// <param name="page"></param>
        /// <param name="postId"></param>
        /// <returns></returns>
        public PagedResultDto<CommentItemResponse> GetComments(PagedResultRequestDto page, CommentFilter filter)
        {
            var query = Repo.GetQuery().Where(comment => !comment.IsDeleted && comment.PostId == filter.PostId && comment.ReplyId == null);

            if (!string.IsNullOrEmpty(filter.CommentId))
            {
                query = query.Where(t => t.Id == filter.CommentId);
            }

            var wxUserQuery = WeixinUserRepo.GetQuery();

            var comments = query.Join(wxUserQuery, t => t.WxUId, s => s.Id, (comment, wxuser) => new CommentItemResponse
            {
                CommentId = comment.Id,
                WxUId = comment.WxUId,
                WxUName = wxuser.Nickname,
                CreateAt = comment.CreateAt,
                Content = comment.Content,
                Avatar = wxuser.Avatar
            }).OrderByDescending(t => t.CreateAt).Skip(page.SkipCount).Take(page.MaxResultCount).ToList();

            int total = query.Count();

            return new PagedResultDto<CommentItemResponse>(total, comments);
        }

        /// <summary>
        /// 获取评论详细
        /// </summary>
        /// <param name="commentId"></param>
        /// <returns></returns>
        public CommentItemResponse GetComment(string commentId)
        {
            var query = Repo.GetQuery().Where(comment => !comment.IsDeleted && comment.Id == commentId);

            var wxUserQuery = WeixinUserRepo.GetQuery();

            var detail = query.Join(wxUserQuery, t => t.WxUId, s => s.Id, (comment, wxuser) => new CommentItemResponse
            {
                CommentId = comment.Id,
                WxUId = comment.WxUId,
                WxUName = wxuser.Nickname,
                CreateAt = comment.CreateAt,
                Content = comment.Content,
                Avatar = wxuser.Avatar,
                PostId = comment.PostId
            }).FirstOrDefault();

            return detail;
        }

        /// <summary>
        /// 获取回复
        /// </summary>
        /// <param name="page"></param>
        /// <param name="replyRootId"></param>
        /// <returns></returns>
        public List<ReplyResponse> GetReplies(PagedResultRequestDto page, ReplyFilter filter)
        {
            var query = Repo.GetQuery().Where(comment => !comment.IsDeleted && comment.ReplyRootId == filter.ReplyRootId);
            var parent_query = Repo.GetQuery().Where(comment => !comment.IsDeleted && comment.ReplyRootId == filter.ReplyRootId);

            query = query.Include(t => t.WxUser);
            parent_query = parent_query.Include(t => t.WxUser);

            // 排除制定要排除的评论
            if (filter.ExcludeCommentIds != null && filter.ExcludeCommentIds.Count > 0)
            {
                query = query.Where(t => !filter.ExcludeCommentIds.Contains(t.Id));
                parent_query = parent_query.Where(t => !filter.ExcludeCommentIds.Contains(t.Id));
            }

            var result = query.GroupJoin(
                parent_query,
                reply => reply.ReplyId,
                parent => parent.Id,
                (reply, parents) => new { reply = reply, parent = parents }
               )
                .SelectMany(t => t.parent.DefaultIfEmpty(),
                    (collection, parent) => new ReplyResponse
                    {
                        UId = collection.reply.WxUId,
                        UName = collection.reply.WxUser.Nickname,
                        Avatar = collection.reply.WxUser.Avatar,
                        CreateAt = collection.reply.CreateAt,
                        Content = collection.reply.Content,
                        CommentId = collection.reply.Id,

                        ParentContent = parent.Content,
                        ParentUName = parent.WxUser.Nickname,
                        ParentId = parent.Id,
                        ParentUId = parent.WxUId
                    })
            .OrderByDescending(t => t.CreateAt).Skip(page.SkipCount).Take(page.MaxResultCount).ToList();



            return result;
        }

        /// <summary>
        /// 获取评论我的评论
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="commentIdsExcluded">被排除的评论/回复ID</param>
        /// <returns></returns>
        public virtual ResponseBase GetMyComments(string uid, List<string> commentIdsExcluded)
        {
            var getMyComments = CommandPool.GetSQL("get-my-comments");

            // 包一层进行排序
            getMyComments = $"SELECT * FROM ({getMyComments}) _ where CommentId Not In ?commentIdsExcluded  ORDER BY CommentAt DESC limit 0, 15";

            var myComments = PostRepo.Query<MyCommentResponse>(getMyComments, new { uid, commentIdsExcluded });

            return new ResponseBase() { Result = myComments.ToList() };
        }
    }
}
